package com.jintu.portal.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.concurrent.*;

/**
 * @author very
 */
@Slf4j
@Component("blockThreadPool")
public class BlockThreadPool {

    @Resource(name = "blockThreadPoolConfig")
    private BlockThreadPoolConfig config;

    private final TimeUnit timeUnit = TimeUnit.MILLISECONDS;
    private ExecutorService threadPool;

    @PostConstruct
    private void getPool() {
        threadPool = new ThreadPoolExecutor(
                config.getCore(),
                config.getMax(),
                config.getKeepalive(),
                timeUnit,
                new ArrayBlockingQueue<>(400),
                createThreadFactory(),
                (Runnable r, ThreadPoolExecutor executor) -> {
                    if (!executor.isShutdown()) {
                        try {
                            executor.getQueue().put(r);
                        } catch (InterruptedException e) {
                            log.error(e.toString(), e);
                        }
                    }
                });

    }


    private ThreadFactory createThreadFactory() {
        return r -> {
            Thread t = new Thread(r);
            t.setName("BlockThreadPool-" + System.currentTimeMillis());
            return t;
        };
    }

    public ExecutorService getThreadPool() {
        return threadPool;
    }

    @Configuration("blockThreadPoolConfig")
    @ConfigurationProperties(prefix = "thread-pool")
    static class BlockThreadPoolConfig {
        private Integer core;
        private Integer max;
        private Long keepalive;

        public Integer getCore() {
            return core;
        }

        public void setCore(Integer core) {
            this.core = core;
        }

        public Integer getMax() {
            return max;
        }

        public void setMax(Integer max) {
            this.max = max;
        }

        public Long getKeepalive() {
            return keepalive;
        }

        public void setKeepalive(Long keepalive) {
            this.keepalive = keepalive;
        }
    }
}
